/*!
 * # 模块 JS:
 *  Creating - 新通知
 * 
 * # 描述:
 *  提供用户创建和发送通知的功能。
 * 
 * Copyright (c), 上海沃恩信息科技有限公司.
 * All rights reserved.
 * Licensed under BSD (https://www.pittypat.work/bsd.html).
 */

/*
 * @param {Object} $    jQuery 命名空间。
 * @param {Object} $$   pittypat 命名空间。
 * @param {Object} _mod 模块 Apps (应用与功能) 的命名空间。
 * 
 * 使用 pittypat.namespace('...') 以确保 _mod 命名空间是存在的。
 * 
 * 更多说明请参见：
 * https://www.pittypat.work/com/waln/pittypat/coding/help/index.html#js。
 */
(function ($, $$, _mod) {
    'use strict';

    /*
     * 为登录用户注册一个处理函数。
     * 由于没有为匿名用户注册处理函数，那么当发现用户尚未登录时，则会默认跳转到首页（登录页）。
     * 
     * 如果需要为匿名用户添加处理逻辑，应该使用如下格式的代码：
     * $$({
     *     authorized: function (_) {
     *         ...
     *     },
     *     anonymous: function (_) {
     *         // 跳转到自定义的登录页面
     *         window.location = '../../../../login.html';
     *     }
     * });
     * 
     * 如果需要自定义登录页面，则可能还需要添加 init 等处理函数。详细帮助请参见：
     * https://www.pittypat.work/com/waln/pittypat/ref/help/pittypat.js.html#pittypat。
     *
     * 参数 _ 的定义如下：
     * {
     *    user:  {Object},  // (只读)当前用户的用户信息
     *    app:   {Object},  // (只读)当前应用的命名空间，如果无法定位，则为 null
     *    mod:   {Object},  // (只读)当前模块的命名空间，如果无法定位，则为 null
     *    init:  {Boolean}, // (只读)是否正在初始化页面
     *    first: {Boolean}, // (只读)是否首次执行 authorized
     *    data:  {any}      // (读写)前述的 data 数据，或 data 函数返回的结果
     * }
     */
    $$(function (_) {
        var
            // 模块 UI 命名空间
            _ui = _mod.ui = _mod.ui || {},
            // 模块 API 命名空间
            _api = _mod.api,
            // body > main
            $main = $('main'),
            // 对话框中接收人列表
            $receivers = $('#receivers');

        if (_.init) {
            // 在当前已经加载行数的基础上增加指定的行数
            function setLoadedSummary() {
                if (arguments.length < 1) {
                    return;
                }

                // 总行数和已加载行数
                var $loadedRows = $('#loaded-rows'),
                    $totalRows = $('#total-rows'),
                    totalRows = 0,
                    loadedRows = Long.fromString($loadedRows.text() || '0').add(arguments[0]);

                if (arguments.length == 1) {
                    // 此时认为只有提供了一个增量
                    totalRows = Long.fromString($totalRows.text() || '0').add(arguments[0]);
                } else {
                    // 第二个参数
                    totalRows = Long.fromValue(arguments[1]);
                }

                $loadedRows.text(loadedRows);
                $totalRows.text(totalRows);

                // 如果已经加载的行数等于或超过了总行数，隐藏加载更多按钮
                $('#load-more').css('display', loadedRows.gte(totalRows) ? 'none' : 'flex');
            }

            /*
             * User 结构如下：
             * {
             * }
             */
            _ui.receiver = {
                /*
                 * User 对象对应的 DOM HTML。
                 */
                get html() {
                    return '<article class="pt-row pt-model model-receiver">' +
                        '    <hr />' +
                        '    <header class="hover">' +
                        '        <div class="pt-row-icon">' +
                        '            <i class="pt-row-toggle material-icons mdc-ripple-surface mdc-ripple-surface--primary mdc-theme--primary" data-mdc-ripple-is-unbounded data-mdc-auto-init="MDCRipple">check_box_outline_blank</i>' +
                        '        </div>' +
                        '        <div class="pt-row-info">' +
                        '            <div>' +
                        '                <span class="pt-model-prop model-receiver-name"></span>' +
                        '            </div>' +
                        '        </div>' +
                        '    </header>' +
                        '</article>';
                },

                /*
                 * 将指定的 App 对象添加到指定 DOM 列表的指定位置。
                 * 
                 * @param {any}    args   _api.list 的 args 事件创建的参数。
                 * @param {Object} model  一个 App 对象。
                 * @param {Number} pos    插入位置，非数字将清空现有列表，小于 0 将添加到最后。
                 * @param {jQuery} $list  要插入的 DOM 列表。
                 */
                insert: function (args, model, pos, $list) {
                    if (!model) {
                        // 没有提供 App 对象
                        return null;
                    }

                    if (!$list || !$list.length) {
                        // 目标元素列表
                        $list = $receivers;
                    }

                    if (!$$.util.is.int(pos)) {
                        // 添加到列表最后
                        pos = -1;
                    }

                    // 目前位置上当前元素
                    var $next = pos >= 0 ? $list.children('.model-receiver').eq(pos) : null,
                        $model = null;

                    if ($next && $next.length) {
                        // 插入到目标元素之前
                        $model = $(_ui.receiver.html).insertBefore($next);
                    } else {
                        // 添加到列表最后
                        $model = $(_ui.receiver.html).appendTo($list);
                    }

                    // 将对象属性更新到目标元素
                    return _ui.receiver.update(args, model, $model, $list).mdcInit();
                },

                /*
                 * 将指定的 App 对象数组添加到指定 DOM 列表的指定位置。
                 * 
                 * @param {any}    args  _api.list 的 args 事件创建的参数。
                 * @param {Object} models 一个 App 对象的数组。
                 * @param {Number} pos   插入位置，非数字将清空现有列表，小于 0 将添加到最后。
                 * @param {jQuery} $list 要插入的 DOM 列表。
                 */
                insertAll: function (args, models, pos, $list) {
                    if (!$list || !$list.length) {
                        // 目标元素列表
                        $list = $receivers;
                    }

                    if (args.pageIndex === '1') {
                        // 清空现有列表
                        $list.empty();
                        // 添加到列表最后
                        pos = -1;
                    }

                    if (models && models.length) {
                        if (pos <= 0) {
                            // 添加到最前或最后
                            models.each(function (model) {
                                _ui.receiver.insert(args, model, pos, $list);
                            });
                        } else {
                            // 添加到指定位置
                            models.each(function (model, i) {
                                _ui.receiver.insert(args, model, pos + i, $list);
                            });
                        }
                    }

                    return $list;
                },

                /*
                 * 将指定的 App 对象更新到现有的 DOM。
                 * 
                 * @param {any}    args  _api.list 的 args 事件创建的参数。
                 * @param {Object} model  一个 App 对象。
                 * @param {jQuery} $model 现有的 DOM。
                 * @param {jQuery} $list 隶属的 DOM 列表。
                 */
                update: function (args, model, $model, $list) {
                    if (!$model || !$model.length) {
                        // 没有提供 $model 时根据 model 或 args 查找目标元素
                        $model = $('#model-receiver-' + model.userId);
                    }

                    if (model && $model.length) {
                        var $h = $model
                            .attr('id', 'model-receiver-' + model.userId)
                            .data('model', model)
                            .children('header');

                        $h.find('.model-receiver-name').text(model.name);
                    }

                    return $model;
                }
            };

            _api.receivers
                .on('args', function (e) {
                    e.args = {
                        pageIndex: $('#select-receivers-page-index').val(),
                        name: $('#select-receivers-name').val()
                    };
                })
                .on('success', function (e) {
                    _ui.receiver.insertAll(e.args, e.result.list);

                    if (e.args.pageIndex == '1') {
                        $('#loaded-rows').text('0');
                    }

                    // 总行数和已加载行数
                    setLoadedSummary(e.result.list.length, e.result.totalRows);
                })
                .on('load', function () {
                    $$.ui.msg = '';
                });
            
            $('#selected-receivers').on('click', '.selected-receiver>i', function () {
                $(this).parent().remove();
            });

            // 搜索用户
            $('#select-receivers-button').on('click', function () {
                $('#select-receivers-page-index').val(1);
                $$.ui.msg = '...';
                _api.receivers();
            });

            // 加载更多
            $('#load-more').on('click', function () {
                var $pi = $('#select-receivers-page-index'),
                    pageIndex = Long.fromValue($pi.val()).add(1);

                $pi.val(pageIndex);

                $$.ui.msg = '...';
                _api.receivers();
            });

            // 全选按钮
            $('#select-receivers-dialog-body>.pt-row').on('beforeselect', function (e) {
                e.affectChildren = true;
            });

            // 确定删除按钮的显示状态
            const MAX_RECEIVERS = 800;
            $('#receivers')
                .on('beforeselect', '.model-receiver', function (e) {
                    if (e.selected) {
                        var $sd = $('#selected-receivers>div'),
                            $all = $sd.children();
                        if ($all.length > MAX_RECEIVERS) {
                            $$.ui.msg = '不能超过 ' + MAX_RECEIVERS + ' 位接收人，请至少移除 ' + ($all.length - MAX_RECEIVERS) + ' 位。';
                            e.cancel = true;
                            return;
                        }

                        if ($('#selected-receiver-' + e.model.id).length < 1) {
                            $('<span class="selected-receiver" id="selected-receiver-' + e.model.id + '"><b></b><i class="material-icons">cancel</i></span>')
                                .appendTo($sd)
                                .children('b').text(e.model.name);
                        }
                    } else {
                        $('#selected-receiver-' + e.model.id).remove();
                    }
                    e.affectParent = true;
                });

            var snackbar = new mdc.snackbar.MDCSnackbar(document.getElementById('snackbar')),
                $file = $('#attachment-file'),
                $progress = $('#upload-progress>span'),
                $attachment = $('#attachment');

            // 选择附件文件
            $('#upload-attachment').on('click', function () {
                $file.trigger('click');
            });

            // 上传附件文件
            $('#attachment-file').on('change', function () {
                var file = $file[0].files.length ? $file[0].files[0] : null;
                if (file == null) {
                    return;
                }

                if (file.name.length > 100) {
                    $$.ui.msg = '文件名称超过了 100 个字符。';
                    return;
                }

                $('#upload-attachment,#delete-attachment').prop('disabled', true);

                var oldFile = $attachment.css('display', 'none').data('file');
                $progress.parent().css('display', 'block');

                _api.upload
                    // 获取文件列表
                    .one('files', function (e) {
                        // 只上传第一个文件
                        e.files = $file[0].files;
                    })

                    // 上传进度
                    .one('progress', function (e) {
                        $progress.css('width', Math.min(100, Math.max(0, e.percent)) + '%');
                    })

                    // POST 操作的 data
                    .one('data', function (e) {
                        var url = e.files[0].url;
                        e.data = {
                            name: e.files[0].name,
                            mime: e.files[0].type,
                            size: e.files[0].size,
                            // 保存时添加一个根路径前缀
                            url: url.startsWith('~') ? url : ('~' + url)
                        };
                    })

                    // 当设置成功后关闭对话框，刷新导航和当前列表
                    .one('success', function (e) {
                        $attachment
                            .data('file', e.result)
                            .val(e.result.name + ' (' + (e.result.size / 1024).toFixed(2) + ' KB)')
                            .css('display', 'flex');
                        $progress.css('width', '0').parent().css('display', 'none');
                        $('#upload-attachment,#delete-attachment').prop('disabled', false);

                        // 上传新文件成功后，删除原来的文件
                        if (oldFile) {
                            // 如果此前已经上传过文件，则首先删除该文件
                            _api.deleteAttachment
                                .one('args', function (e) {
                                    e.args = oldFile.id;
                                })();
                        }
                    })
                    .one('error', function (e) {
                        $('#upload-attachment').prop('disabled', false);
                        $('#delete-attachment').prop('disabled', !oldFile);
                        $$.ui.msg = e.message;
                    })();
            });

            function deleteAttachment() {
                var file = $attachment.data('file');
                if (file) {
                    _api.deleteAttachment
                        .one('args', function (e) {
                            e.args = file.id;
                        })
                        .one('success', function () {
                            $('#delete-attachment').prop('disabled', true);
                            $attachment.data('file', null).val('');
                        })();
                }
            }

            // 删除附件
            $('#delete-attachment').on('click', deleteAttachment);
            $(window).on('beforeunload', deleteAttachment);

            // 发送
            _api.send
                .on('args', function (e) {
                    var receivers = [], start = 'selected-receiver-'.length,
                        file = $('#attachment').data('file');

                    $('.selected-receiver').each(function () {
                        receivers.push(this.id.substr(start));
                    });

                    e.args = {
                        receivers: receivers.join(','),
                        urgency: $('#urgency').val(),
                        group: $('#group').val(),
                        title: $('#title').val(),
                        summary: $('#summary').val(),
                        body: $('#body').val(),
                        attachmentId: file ? file.id : ''
                    };
                })
                .on('success', function (e) {
                    $('#selected-receivers>div').empty();
                    $('#urgency').val('1');
                    $('#group').val('');
                    $('#title').val('');
                    $('#summary').val('');
                    $('#body').val('');
                    $('#delete-attachment').prop('disabled', true);
                    $attachment.data('file', null).val('');
                    snackbar.show({
                        message: '成功发送 ' + e.result + ' 条消息！',
                        actionHandler: $.noop,
                        actionText: '关闭'
                    });
                })
                .on('load', function () {
                    $$.ui.msg = '';
                });

            $('#send').on('click', function () {
                _api.send();
            });

            $main.mdcInit();
        }
    });
})(jQuery, pittypat, pittypat.namespace('waln.notifying.creating'));
